package com.imflea.zero.service.task.impl;



import com.imflea.zero.model.entity.task.ScheduleTask;
import com.imflea.zero.service.task.IScheduledTaskJobService;
import com.imflea.zero.service.task.IScheduledTaskRunnerService;
import com.imflea.zero.utils.ZeroApplicationContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.ReentrantLock;


@Slf4j
@Service
public class ScheduledTaskRunnerServiceImpl implements IScheduledTaskRunnerService {

    @Value("${task.enabled:true}")
    private Boolean taskEnable;

    /**
     * 可重入锁
     */
    private ReentrantLock lock = new ReentrantLock();
    /**
     * 定时任务线程池
     */
    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;


    /**
     * 存放已经启动的任务map
     */
    private Map<String, ScheduledFuture> scheduledFutureMap = new ConcurrentHashMap<>();


    @Override
    public Boolean start(String taskKey, ScheduleTask scheduled) {
        log.info(">>>>>> 启动任务 {} 开始 >>>>>>", taskKey);
        //添加锁放一个线程启动，防止多人启动多次
        lock.lock();
        log.info(">>>>>> 添加任务启动锁完毕");
        try {
            //校验是否已经启动
            if (this.isStart(taskKey)) {
                log.info(">>>>>> 当前任务已经启动，无需重复启动！");
                return false;
            }
            //查询配置
//            if (scheduled == null)
//                scheduled = this.getByTaskKey(taskKey);
            if (scheduled == null)
                return false;
            //启动任务
            this.doStartTask(scheduled);
        } finally {
            // 释放锁
            lock.unlock();
            log.info(">>>>>> 释放任务启动锁完毕");
        }
        log.info(">>>>>> 启动任务 {} 结束 >>>>>>", taskKey);
        return true;
    }


    @Override
    public Boolean stop(String taskKey) {
        log.info(">>>>>> 进入停止任务 {}  >>>>>>", taskKey);
        //当前任务实例是否存在
        boolean taskStartFlag = scheduledFutureMap.containsKey(taskKey);
        log.info(">>>>>> 当前任务实例是否存在 {}", taskStartFlag);
        if (taskStartFlag) {
            //获取任务实例
            ScheduledFuture scheduledFuture = scheduledFutureMap.get(taskKey);
            //关闭实例
            boolean cancel = scheduledFuture.cancel(true);
            log.info("cancel:{}", cancel);
            //删除关闭的任务实例
            scheduledFutureMap.remove(taskKey);
        }
        log.info(">>>>>> 结束停止任务 {}  >>>>>>", taskKey);
        return taskStartFlag;
    }


    @Override
    public Boolean restart(String taskKey, ScheduleTask task) {
        log.info(">>>>>> 进入重启任务 {}  >>>>>>", taskKey);
        //先停止
        this.stop(taskKey);
        //查询配置
//        if (scheduled == null)
//            scheduled = this.getByTaskKey(taskKey);
        if (task == null)
            return false;
        //再启动
        return this.start(taskKey, task);
    }

    /**
     * 初始化  ==> 启动所有正常状态的任务
     *
     * @param tasks
     */
    @Override
    public void initAllTask(List<ScheduleTask> tasks) {
        if (!taskEnable) {
            log.info("配置文件禁用了定时任务----");
            return;
        }


        log.info("初始化  ==> 启动所有正常状态的任务开始 ！size={}", tasks == null ? 0 : tasks.size());
        if (tasks == null || tasks.size() < 1) {
            return;
        }
        for (ScheduleTask task : tasks) {
            //任务 key
            String taskKey = task.getTaskKey();
            Boolean isEnable = ("1").equals(task.getStatus());
            //校验是否已经启动
            if (this.isStart(taskKey)) {
                if (isEnable) {
                    // 重启任务
                    this.restart(taskKey, task);
                } else {
                    this.stop(taskKey);
                }


            } else {
                if (isEnable) {
                    // 启动任务
                    this.doStartTask(task);
                }
            }
        }
        log.info("初始化  ==> 启动所有正常状态的任务结束 ！");
    }

    /**
     * 执行启动任务
     */
    private void doStartTask(ScheduleTask task) {
        if (task == null)
            return;
        //任务key
        String taskKey = task.getTaskKey();
        //定时表达式
        String taskCron = task.getCron();
        //获取需要定时调度的接口
        IScheduledTaskJobService scheduledTaskJob = ZeroApplicationContextUtil.getBean(taskKey, IScheduledTaskJobService.class);
        log.info(">>>>>> 任务 [ {} ] ,cron={}", task.getName(), taskCron);
        ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(scheduledTaskJob, (TriggerContext triggerContext) -> new CronTrigger(taskCron).nextExecutionTime(triggerContext));
        //将启动的任务放入 map
        scheduledFutureMap.put(taskKey, scheduledFuture);
    }

    /**
     * 任务是否已经启动
     */
    private Boolean isStart(String taskKey) {
        //校验是否已经启动
        if (scheduledFutureMap.containsKey(taskKey)) {
            if (!scheduledFutureMap.get(taskKey).isCancelled()) {
                return true;
            }
        }
        return false;
    }

}